package com.stoney.http;

import java.util.Collections;
import java.util.Map;

/**
 * Created by Stony on 2015/12/12.
 */
public abstract class Request<T> implements Comparable<Request<T>> {

    private static final int SLOW_REQUEST_THRESHOLD_MS = 3000;

    private int method;
    private String url;
    private String bodyContentType;
    private byte[] postBody;
    private String postBodyContentType;
    private byte[] body;
    private Map<String, String> headers;
    private int timeoutMs = SLOW_REQUEST_THRESHOLD_MS;
    private boolean canceled;
    /** The request queue this request is associated with. */
    private RequestQueue mRequestQueue;
    private Integer mSequence = 1;

    /** Listener interface for errors. */
    private final Response.ErrorListener mErrorListener;

    public Request(String url, Response.ErrorListener listener) {
        this(Method.DEPRECATED_GET_OR_POST, url, listener);
    }
    public Request(int method, String url, Response.ErrorListener listener) {
        this.method = method;
        this.url = url;
        mErrorListener = listener;
    }


    protected abstract Response<T> parseNetworkResponse(NetworkResponse networkResponse);
    protected abstract void deliverResponse(T result);

    /**
     * Delivers error message to the ErrorListener that the Request was
     * initialized with.
     *
     * @param error Error details
     */
    public void deliverError(RequestFailureError error) {
        if (mErrorListener != null) {
            mErrorListener.onErrorResponse(error);
        }
    }


    public interface Method {
        int DEPRECATED_GET_OR_POST = -1;
        int GET = 0;
        int POST = 1;
        int PUT = 2;
        int DELETE = 3;
    }

    /**
     * Associates this request with the given queue. The request queue will be notified when this
     * request has finished.
     */
    public void setRequestQueue(RequestQueue requestQueue) {
        mRequestQueue = requestQueue;
    }
    public int getMethod() {
        return method;
    }

    public String getUrl() {
        return url;
    }

    public String getBodyContentType() {
        return bodyContentType;
    }

    public byte[] getPostBody() {
        return postBody;
    }

    public String getPostBodyContentType() {
        return postBodyContentType;
    }

    public byte[] getBody() {
        return body;
    }

    public Map<String, String> getHeaders() {
        return Collections.emptyMap();
    }

    public int getTimeoutMs() {
        return timeoutMs;
    }



    public void addMarker(String tag) {

    }

    public void markDelivered() {

    }

    public boolean isCanceled() {
        return canceled;
    }
    public void finish(String tag) {
        if (mRequestQueue != null) {
            mRequestQueue.finish(this);
        }
    }
    public Priority getPriority() {
        return Priority.NORMAL;
    }
    @Override
    public int compareTo(Request<T> other) {
        Priority left = this.getPriority();
        Priority right = other.getPriority();
        return left == right ?
                this.mSequence - other.mSequence :
                right.ordinal() - left.ordinal();
    }

    public enum Priority {
        LOW,
        NORMAL,
        HIGH,
        IMMEDIATE
    }

    /**
     * Sets the sequence number of this request.  Used by {@link RequestQueue}.
     */
    public final void setSequence(int sequence) {
        mSequence = sequence;
    }
}
